# MikroPictures Image Convertor
# Author: Matt Olson
# This script has been tested with python 2.6 and 2.7.
# The Python Imaging Library (PIL) is used: http://www.pythonware.com/products/pil/
#
# Converts image files into C source files to be loaded into program memory.
# Written for development on the Mikromedia board for PIC24.
#
# Input:
# An image file of type supported by your installation of PIL, in RGB format.
#
# Output:
# C source file with a populated image structure using this type:
# typedef Image {
#     int X; // image width
#     int Y; // image height
#     short int *data; /* image data array structure */
# } image;
#

import os, tkFileDialog, pickle
from Tkinter import *
import Image # http://www.pythonware.com/products/pil/

class App(Frame):
	def __init__(self, master=None):
		Frame.__init__(self, master)

		self.scale = StringVar()
		self.scale.set('100')
		self.scaleBoolVar = BooleanVar()

		self.METAFILE_NAME = '.stored_filename'
		
		self.pack()

		self.entryboxLabel = Label(text="input file:")
		self.entryboxLabel.pack()
		self.entrybox = Entry()
		self.entrybox.pack(expand=1, fill='x')
		
		self.scaleFactorLabel = Label(text="scale factor (max side length of output in pixels):")
		self.scaleFactorLabel.pack()
		self.scaleFactor = Entry()
		self.scaleFactor.pack(expand=1, fill='x')
		self.scaleFactor["textvariable"] = self.scale

		self.scaleBool = Checkbutton(text="scale image?", onvalue=True, offvalue=False, variable=self.scaleBoolVar)
		self.scaleBool.select()
		self.scaleBool.pack()

		self.filename = StringVar()
		if os.path.isfile(self.METAFILE_NAME):
			#load stored filename from the last time this program was used
			metafile = open(self.METAFILE_NAME, 'r')
			unpickler = pickle.Unpickler(metafile)
			self.filename.set(unpickler.load())
		else:
			#use default filename (program hasn't been used yet on this system)
			self.filename.set('choose file')
			
		self.entrybox["textvariable"] = self.filename

		self.getfilenamebutton = Button(self, text="Choose file", command=self.choosefile)
		self.getfilenamebutton.pack(side="left")

		self.gobutton = Button(self, text="Convert image", command=self.convert)
		self.gobutton.pack(side="left")

		self.quitbutton = Button(self, fg="red", text="Quit", command=self.finish)
		self.quitbutton.pack(side="right")

	def convert(self):
		self.im = Image.open( self.filename.get() )
		if self.im.mode != "RGB":
			print 'Image is in ' + self.im.mode + ' mode; must be RGB'
			return
		else:
			print 'Image is in RGB mode.'

		#scale image
		if self.scaleBoolVar.get():
			self.im.thumbnail((int(self.scale.get()), int(self.scale.get())), Image.ANTIALIAS)

		#create file to store converted data
		self.sourcename = self.name_outfile( self.filename.get() )
		self.source = open(self.sourcename, 'w')

		#write output file 
		self.source.write( "#include \"MikroPictures.h\"\n\n" )
		self.source.write( "__psv__ image " + os.path.split(self.filename.get())[1].split('.')[0]+ " __attribute__((space(psv)))" + "  = {\n    " + self.im.size[0].__str__() + ",\n    " + self.im.size[1].__str__() + ",\n    {\n        ")
		self.i = 0
		for pixel in list(self.im.getdata()):
			self.r = int(pixel[0])
			self.g = int(pixel[1])
			self.b = int(pixel[2])
			self.source.write(hex(self.pack_bits(self.r,self.g,self.b)) + ", ")
			self.i += 1
			if self.i == 8:
				self.source.write("\n        ")
				self.i = 0
		self.source.write( "\n    }\n};\n")
		self.source.close()

		#print out some info for the user
		print "Output file:" 
		print self.sourcename
		print "Output image dimensions:" 
		print self.im.size.__str__()
		print "Output image bytes:"
		print 2 * self.im.size[0] * self.im.size[1]

	#generate output file name
	def name_outfile(self, filename):
		return os.path.splitext(filename)[0] + ".c"

	#open file explorer to select file
	def choosefile(self):
		self.filename.set(tkFileDialog.askopenfilename())

	#bit packing
	def pack_bits(self, r, g, b):
		return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)
	
	#save current filename for the future and quit
	def finish(self):
		stored_filename = open(self.METAFILE_NAME, 'w')
		pickler = pickle.Pickler(stored_filename)
		pickler.dump(self.filename.get())
		self.quit()

root = Tk()
root.title("MikroPictures Image Convertor")
app = App(master=root)
app.mainloop()
root.destroy()

